package org.sixtynine.stock.service.file;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.sixtynine.stock.Constants;
import org.sixtynine.stock.ReturnData;
import org.sixtynine.stock.Constants.CommonData;
import org.sixtynine.stock.entity.BaseEntity;
import org.sixtynine.stock.entity.Company;
import org.sixtynine.stock.entity.Sector;
import org.sixtynine.stock.entity.SubSector;
import org.sixtynine.stock.service.content.DataManagerService;
import org.springframework.stereotype.Component;

/**
 * @author Thilan
 * 
 */
@Component(ExcelProcessorFactory.FILE_TYPE_SECTOR_LIST)
public class SectorListProcesser extends ExcelProcessor {

	public Map<String, Company> companyMap;
	public Map<String, Sector> sectorMap;
	public Map<String, SubSector> subSectorMap;

	public void init() {
		List<BaseEntity> companyList = DataManagerService
				.getData(CommonData.COMPANY.toString());

		List<BaseEntity> sectorList = DataManagerService
				.getData(CommonData.SECTOR.toString());

		List<BaseEntity> subSectorList = DataManagerService
				.getData(CommonData.SUB_SECTOR.toString());

		sectorMap = new HashMap<String, Sector>();
		if (sectorList != null) {
			for (BaseEntity baseEntity : sectorList) {
				Sector sector = (Sector) baseEntity;
				sectorMap.put(sector.getCode(), sector);
			}
		}

		subSectorMap = new HashMap<String, SubSector>();
		if (subSectorList != null) {
			for (BaseEntity baseEntity : subSectorList) {
				SubSector subSector = (SubSector) baseEntity;
				subSectorMap.put(subSector.getCode(), subSector);
			}
		}

		companyMap = new HashMap<String, Company>();
		if (companyList != null) {
			for (BaseEntity baseEntity : companyList) {
				Company company = (Company) baseEntity;

				companyMap.put(company.getCode(), company);
			}
		}
	}

	@Override
	public ReturnData<List<? extends BaseEntity>> process(String filePath) {
		ReturnData<List<? extends BaseEntity>> returnData = new ReturnData<List<? extends BaseEntity>>(
				Constants.SUCCESS, "");

		// initialized if maps are not created
		if (sectorMap == null) {
			init();
		}

		try {

			List<Sector> sectors = new ArrayList<Sector>();
			File file = new File(filePath);

			// Get the workbook instance for XLS file
			Workbook workbook = WorkbookFactory.create(file);

			// Get first sheet from the workbook
			Sheet sheet = workbook.getSheetAt(0);

			// Get iterator to all the rows in current sheet
			Iterator<Row> rowIterator = sheet.iterator();
			int rowIndex = 0;

			while (rowIterator.hasNext()) {

				String sectorCode = null;
				String sectorName = null;

				Row row = rowIterator.next();
				// Get iterator to all cells of current row
				Iterator<Cell> cellIterator = row.cellIterator();

				if (rowIndex == 0) {
					Cell firstCell = row.getCell(0);
					if (firstCell == null) {
						returnData.setNo(Constants.ERROR);
						returnData
								.setMsg("Error file format, data should be started from first row and column");
						return returnData;
					}
					rowIndex++;
					continue;
				}

				int colIndex = 0;
				while (cellIterator.hasNext()) {
					Cell cell = cellIterator.next();
					Object cellVal = getCellValue(cell);
					switch (colIndex) {
					case 0:
						ReturnData<?> codeReturn = validateCompanyCode(cellVal,
								rowIndex);
						if (codeReturn._isSuccess()) {
							sectorCode = (String) cellVal;
						} else {
							returnData.setNo(Constants.ERROR);
							returnData.setMsg(codeReturn.getMsg());
							return returnData;
						}
						break;
					case 1:
						ReturnData<?> nameReturn = validateForText(cellVal,
								"Sector Name", rowIndex);
						if (nameReturn._isSuccess()) {
							sectorName = (String) cellVal;
						} else {
							returnData.setNo(Constants.ERROR);
							returnData.setMsg(nameReturn.getMsg());
							return returnData;
						}
						break;

					default:
						break;
					}

					colIndex++;
				}

				Sector sector = sectorMap.get(sectorCode);
				if (sector == null) {
					sector = new Sector();
				}

				sector.setCode(sectorCode);
				sector.setName(sectorName);

				sectors.add(sector);
				rowIndex++;
			}

			returnData.setData(sectors);

		} catch (IOException e) {
			e.printStackTrace();
			returnData.setNo(Constants.ERROR);
			returnData.setMsg(e.getMessage());
		} catch (InvalidFormatException e) {
			e.printStackTrace();
			returnData.setNo(Constants.ERROR);
			returnData.setMsg(e.getMessage());
		}

		return returnData;
	}

	private ReturnData<?> validateCompanyCode(Object cellVal, int row) {
		ReturnData<String> returnData = new ReturnData<String>(
				Constants.SUCCESS, "");

		if (!validateForNull(cellVal)) {
			returnData.setNo(Constants.ERROR);
			returnData.setMsg("Sector code cannot be null at row " + row);
		}

		if (cellVal instanceof String) {
			String sectorCode = (String) cellVal;

			// TODO validate format - with regular expression ?

		} else {
			returnData.setNo(Constants.ERROR);
			returnData.setMsg("Sector code is in the wrong format at row "
					+ row);
		}

		return returnData;
	}

}
